<template>
  <transition name="modal">
    <div v-if="isOpen" class="fixed inset-0 z-[9998] overflow-y-auto" :class="[overlayClass]"
      @click.self="handleOutsideClick">
      <div class="flex items-center justify-center min-h-screen p-4" :class="[containerClass]">
        <div ref="modalRef" class="relative bg-white rounded-lg shadow-xl w-full" :class="[modalClass, maxWidthClass]">
          <!-- Header -->
          <div v-if="showHeader" class="flex items-center justify-between p-4 border-b" :class="[headerClass]">
            <h3 class="text-lg font-medium" :class="[titleClass]">
              {{ title }}
            </h3>
            <button v-if="showCloseButton" @click="close" class="p-1 rounded-full hover:bg-gray-100"
              :class="[closeButtonClass]">
              <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          <!-- Content -->
          <div class="p-4" :class="[contentClass]">
            <slot></slot>
          </div>

          <!-- Footer -->
          <div v-if="showFooter" class="p-4 border-t" :class="[footerClass]">
            <slot name="footer">
              <div class="flex justify-end space-x-2">
                <button v-if="showCancelButton" @click="handleCancel"
                  class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200"
                  :class="[cancelButtonClass]">
                  {{ cancelText }}
                </button>
                <button v-if="showConfirmButton" @click="handleConfirm"
                  class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700"
                  :class="[confirmButtonClass]">
                  {{ confirmText }}
                </button>
              </div>
            </slot>
          </div>
        </div>
      </div>
    </div>
  </transition>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'

const props = withDefaults(defineProps<{
  isOpen: boolean
  title?: string
  showHeader?: boolean
  showFooter?: boolean
  showCloseButton?: boolean
  showCancelButton?: boolean
  showConfirmButton?: boolean
  cancelText?: string
  confirmText?: string
  closeOnClickOutside?: boolean
  closeOnEsc?: boolean
  maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'
  overlayClass?: string
  containerClass?: string
  modalClass?: string
  headerClass?: string
  titleClass?: string
  contentClass?: string
  footerClass?: string
  closeButtonClass?: string
  cancelButtonClass?: string
  confirmButtonClass?: string
}>(), {
  title: 'Modal Title',
  showHeader: true,
  showFooter: true,
  showCloseButton: true,
  showCancelButton: true,
  showConfirmButton: true,
  cancelText: 'Cancel',
  confirmText: 'Confirm',
  closeOnClickOutside: true,
  closeOnEsc: true,
  maxWidth: 'md',
  overlayClass: 'bg-black bg-opacity-50',
})

const emit = defineEmits<{
  (e: 'update:isOpen', value: boolean): void
  (e: 'close'): void
  (e: 'cancel'): void
  (e: 'confirm'): void
}>()

const modalRef = ref<HTMLElement | null>(null)

const maxWidthClass = computed(() => {
  const classes = {
    sm: 'max-w-sm',
    md: 'max-w-md',
    lg: 'max-w-lg',
    xl: 'max-w-xl',
    '2xl': 'max-w-2xl',
    '3xl': 'max-w-3xl',
    full: 'max-w-full',
  }
  return classes[props.maxWidth]
})

const close = () => {
  emit('update:isOpen', false)
  emit('close')
}

const handleCancel = () => {
  emit('cancel')
  close()
}

const handleConfirm = () => {
  emit('confirm')
}

const handleOutsideClick = () => {
  if (props.closeOnClickOutside) {
    close()
  }
}

const handleKeydown = (e: KeyboardEvent) => {
  if (props.isOpen && props.closeOnEsc && e.key === 'Escape') {
    close()
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleKeydown)
})

onBeforeUnmount(() => {
  document.removeEventListener('keydown', handleKeydown)
})

watch(() => props.isOpen, (newVal) => {
  if (newVal) {
    document.body.style.overflow = 'hidden'
  } else {
    document.body.style.overflow = ''
  }
})
</script>

<style scoped>
.modal-enter-active,
.modal-leave-active {
  transition: opacity 0.3s ease;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}

.modal-enter-active .modal-container,
.modal-leave-active .modal-container {
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.modal-enter-from .modal-container,
.modal-leave-to .modal-container {
  transform: translateY(-20px);
  opacity: 0;
}
</style>